package main

import (
	"context"
	"encoding/json"
	"net"
	"strconv"

	grpc "google.golang.org/grpc"
	protos "smeb.xyz/pub/websocket-subandpub-cluster/internal/handlerwebsocket/protos"
)

type ManageConsoleServer struct {
}

// GetStatistical implements protos.ManageConsleServiceServer.
func (*ManageConsoleServer) GetStatistical(context.Context, *protos.GetStatisticalRequest) (*protos.GetStatisticalResponse, error) {
	cluster := Redis.SCard(context.Background(), "wsserver").Val()
	conn := Redis.SCard(context.Background(), ConnId_Redix_key).Val()
	channel := Redis.SCard(context.Background(), Channel_Redis_key).Val()
	return &protos.GetStatisticalResponse{
		Cluster: cluster,
		Conn:    conn,
		Channel: channel,
	}, nil
}

func (m *ManageConsoleServer) GetCluserList(ctx context.Context, msg *protos.GetCluserListRequest) (*protos.GetCluserListResponse, error) {

	s, e := Redis.SMembers(ctx, "wsserver").Result()

	if e != nil {
		return nil, e
	} else {
		return &protos.GetCluserListResponse{ClusterList: s}, nil
	}
}

func (m *ManageConsoleServer) GetClusterInfo(ctx context.Context, msg *protos.GetClusterInfoRequest) (*protos.GetClusterInfoResponse, error) {

	req := &protos.GetServerInfoRequest{
		Servername: msg.Servername,
	}

	b, err := GetServerInfo(msg.Servername, req)

	if err != nil {
		return nil, err
	} else {
		return &protos.GetClusterInfoResponse{
			Servername:     b.Servername,
			Cpu:            b.Cpu,
			Mem:            b.Mem,
			Alloc:          b.Alloc,
			Totalalloc:     b.Totalalloc,
			Sys:            b.Sys,
			HeapInuse:      b.HeapInuse,
			CpupercentList: b.CpupercentList,
		}, nil
	}

}

func (m *ManageConsoleServer) GetConnInfo(ctx context.Context, msg *protos.GetConnInfoRequest) (*protos.GetConnInfoResponse, error) {
	values, err := Redis.SRandMemberN(ctx, ConnId_Redix_key, 100).Result()
	if err != nil {
		return nil, err
	} else {
		count, _ := Redis.SCard(ctx, ConnId_Redix_key).Result()
		// list<str> to list<Conn>
		var connList []*protos.Conn
		for _, str := range values {
			var conn protos.Conn
			if err := json.Unmarshal([]byte(str), &conn); err != nil {
				continue
			}
			connList = append(connList, &conn)
		}
		return &protos.GetConnInfoResponse{
			Total:    count,
			ConnList: connList,
		}, nil
	}
}

func (m *ManageConsoleServer) GetChannels(ctx context.Context, msg *protos.GetChannelsRequest) (*protos.GetChannelsResponse, error) {

	values, err := Redis.SMembers(ctx, Channel_Redis_key).Result()

	if err != nil {
		return nil, err
	} else {
		return &protos.GetChannelsResponse{
			ChannelList: values,
		}, nil
	}
}

func StartManageConsole() {
	lis, err := net.Listen("tcp", ":"+strconv.Itoa(Configs.Http2Port))
	if err != nil {
		ZapLogger.Error("failed to listen: %v", err)
	}

	s := grpc.NewServer()

	protos.RegisterManageConsleServiceServer(s, &ManageConsoleServer{})

	protos.RegisterGrpcServiceServer(s, &GrpcServiceServer{})

	ZapLogger.Info("gRPC server running on port " + strconv.Itoa(Configs.Http2Port))
	if err := s.Serve(lis); err != nil {
		ZapLogger.Fatalf("failed to serve: %v", err)
	}

}
